from django_redis import get_redis_connection
from redis import RedisError
from rest_framework import serializers

from meiduo.utils.exceptions import logger


class ImageCodeCheckSerializer(serializers.Serializer):
    """
    1.校验手机号mobile(在url中通过正则校验), 图片id, 图片内容

    """
    image_code_id = serializers.UUIDField()
    # 手机验证码信息,长度为4
    text = serializers.CharField(max_length=4, min_length=4)

    def validate(self, attrs):
        """
        自定义验证器---验证图片id和内容
        :param attrs:
        :return:
        """
        # 1.获取图片id和text
        image_code_id = attrs["image_code_id"]
        text = attrs["text"]

        # 2.创建redis链接对象,从redis数据库中取出图片id
        redis_conn = get_redis_connection("verify_codes")
        real_image_code = redis_conn.get("image_%s" % image_code_id)

        # 如果未取出,抛出异常
        if not real_image_code:
            raise serializers.ValidationError("图片验证码已失效....")

        # 3.当用户输入图片验证码,已经开始验证动作,不管验证结果通过与否,都将图片信息从redis数据库中删除
        # 防止xxx用程序不停地输入验证码,攻击网站
        try:
            redis_conn.delete("image_%s" % image_code_id)
        except RedisError as e:
            logger.error(e)

        # 4.进行图片验证
        # 从redis中取出的是二进制,需要进行解码
        real_image_code_text = real_image_code.decode()
        if real_image_code_text.lower() != text.lower():
            raise serializers.ValidationError("图片验证码错误")

        # 5.防止恶意注册,对用户手机号进行验证
        mobile = self.context["view"].kwargs["mobile"]
        # get_serializer在创建序列化器对象时,会补充context属性
        # context属性有三个值,request format view(当前的类视图对象)
        # django的类视图对象,kwargs属性保存了路径中的参数

        # 记录发送短信的验证
        send_flag = redis_conn.get("send_flag_%s" % mobile)
        if send_flag:
            raise serializers.ValidationError("请求次数频繁")

        return attrs

